﻿using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;

namespace RayDen.Library.Data.Scene.SCFF
{
    public class EntityCollection : IEnumerable<KeyValuePair<string, Dictionary<string, object>>>, IEnumerable<ConfigEntity>
    {
        public string Type;
        private readonly Dictionary<string, Dictionary<string, object>> items;

        public object this[string name, string param]
        {
            get { return items[name][param]; }
        }

        IEnumerable<ConfigEntity> Entities
        {
            get
            {
                return this.items.Select(item => new ConfigEntity(item.Key, this.Type, item.Value));
            }
        }

        public object this[string path]
        {
            get
            {
                var pathElements = path.Split('.');
                return items[pathElements[0]][pathElements[1]];
            }

            set
            {
                var pathElements = path.Split('.');

                if (!items.ContainsKey(pathElements[0]))
                {
                    items.Add(pathElements[0],
                              new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase)
                                  {
                                      {pathElements[1], value}
                                  });
                } else 

                if (!items[pathElements[0]].ContainsKey(pathElements[1]))
                {
                    items[pathElements[0]].Add(pathElements[1], value);
                } else 
                {
                    items[pathElements[0]][pathElements[1]] = value;
                }
            }

        }

        public EntityCollection(string type=null)
        {
            this.Type = type;
            items = new Dictionary<string, Dictionary<string, object>>(StringComparer.InvariantCultureIgnoreCase);
        }

        public EntityCollection(IDictionary<string, Dictionary<string, object>> data, string type)
        {
            this.Type = type;
            items = new Dictionary<string, Dictionary<string, object>>(data, StringComparer.InvariantCultureIgnoreCase);
        }

        public void SetItem(string name, string parameter, object value)
        {
            items[name][parameter] = value;
        }

        public bool ContainsKey(string path)
        {
            var pathElements = path.Split('.');

            return this.items.ContainsKey(pathElements[0]) && items[pathElements[0]].ContainsKey(pathElements[1]);
        }

        public void AddItem(string path, object value, string sep)
        {
            var pathElements = path.Split(sep.ToCharArray());
            bool entity = value is IEnumerable<KeyValuePair<string, object>>;

            if (!items.ContainsKey(pathElements[0]))
            {
                if (entity)
                    items.Add(pathElements[0],
                              (value as IEnumerable<KeyValuePair<string, object>>).ToDictionary(pair => pair.Key,
                                                                                                pair => pair.Value));
                else
                    items.Add(pathElements[0], new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase));
            }

            if (entity)
            {
                var dic = (value as IEnumerable<KeyValuePair<string, object>>).ToDictionary(pair => pair.Key,pair => pair.Value);
                foreach (var item in dic)
                {
                    if (items[pathElements[0]].ContainsKey(item.Key))
                    {
                        items[pathElements[0]][item.Key] = item.Value;
                    }
                    else
                    {
                        items[pathElements[0]].Add(item.Key, item.Value);
                    }
                }
            }
            else
            {
                if (!items[pathElements[0]].ContainsKey(pathElements[1]))
                {
                    items[pathElements[0]].Add(pathElements[1], value);
                }
                else
                    items[pathElements[0]][pathElements[1]] = value;
            }
        }

        public IEnumerator<KeyValuePair<string, Dictionary<string, object>>> GetEnumerator()
        {
            return this.items.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        IEnumerator<ConfigEntity> IEnumerable<ConfigEntity>.GetEnumerator()
        {
            return this.Entities.GetEnumerator();
        }
    }
}